package org.richin.support.orm.spring;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.impl.CriteriaImpl;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.persister.entity.SingleTableEntityPersister;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.transform.Transformers;
import org.richin.array.util.ArrayUtils;
import org.richin.lang.util.Convert;
import org.richin.support.orm.IHibernateDaoSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import org.springframework.util.Assert;
import org.springside.modules.orm.PropertyFilter;
import org.springside.modules.utils.ReflectionUtils;

@SuppressWarnings("unchecked")
public abstract class SpringDaoSupportImp<T, ID extends Serializable> extends HibernateDaoSupport implements
		IHibernateDaoSupport<T, ID> {
	protected Logger log = LoggerFactory.getLogger(super.getClass());
	protected Class<T> entityClass;
	private boolean cacheable = false;

	public SpringDaoSupportImp() {
		this.entityClass = ReflectionUtils.getSuperClassGenricType(super.getClass());
	}

	public abstract void setSuperSessionFactory(SessionFactory sessionFactory);

	public SpringDaoSupportImp(SessionFactory sessionFactory, Class<T> entityClass) {
		super.setSessionFactory(sessionFactory);// = sessionFactory;
		this.entityClass = entityClass;
	}

	/**
	* 获得总记录数.
	*
	* @param criteria 条件
	* @return 总数
	*/
	public Integer getCount(Criteria criteria) {
		Object result = criteria.setProjection(Projections.rowCount()).uniqueResult();

		return ((Number) result).intValue();
	}

	/**
	 * 取得对象的主键名,辅助函数.
	 *
	 * @param entityClass 实体类型
	 * @return 主键名称
	 */
	public String getIdName(Class entityClass) {
		Assert.notNull(entityClass);
		log.debug("取得对象的主键名,辅助函数:" + entityClass);
		ClassMetadata meta = getSessionFactory().getClassMetadata(entityClass);
		Assert.notNull(meta, "Class " + entityClass + " not define in hibernate session factory.");

		String idName = meta.getIdentifierPropertyName();
		Assert.hasText(idName, entityClass.getSimpleName() + " has no identifier property define.");

		return idName;
	}

	/**
	 * 取得对象的主键值，辅助函数.
	 *
	 * @param entityClass 实体类型
	 * @param entity 实例
	 * @return 主键
	 * @throws NoSuchMethodException 找不到方法
	 * @throws IllegalAccessException 没有访问权限
	 * @throws InvocationTargetException 反射异常
	 */
	public Serializable getId(Class entityClass, Object entity) throws NoSuchMethodException, IllegalAccessException,
			InvocationTargetException {
		Assert.notNull(entity);
		Assert.notNull(entityClass);

		return (Serializable) PropertyUtils.getProperty(entity, getIdName(entityClass));
	}

	public void save(T entity) {
		log.info("saving entity...........");
		Assert.notNull(entity);
		super.getHibernateTemplate().saveOrUpdate(entity);
	}

	public void delete(T entity) {
		Assert.notNull(entity);
		super.getHibernateTemplate().delete(entity);
	}

	public  void delete(ID...ids) {
	if(ArrayUtils.getLength(ids)>1){
		for(int i=0;i<ids.length;i++)
		removeById(ids[i]);
	}else
		this.delete(get(ArrayUtils.first(ids)));
	}

	/**
	* 根据name,value进行模糊查询.
	*
	* @param <T> 实体类型
	* @param entityClass 实体类型
	* @param name 字段名
	* @param value 用来做模糊查询的字段值
	* @return 查询结果
	*/
	public List<T> findByLike(Class<T> entityClass, String propertyName, Object value) {
		return this.createCriteria(entityClass, Restrictions.like(propertyName, value)).list();
	}

	/**
	 * 根据entityClass，生成带排序的Criteria.
	 *
	 * @param <T> 实体类型
	 * @param entityClass 类型
	 * @param orderBy 排序字段名
	 * @param isAsc 是否正序
	 * @param criterions 条件
	 * @return Criteria
	 */
	public Criteria createCriteria(Class<T> entityClass, String orderBy, boolean isAsc, Criterion... criterions) {
		if ((orderBy == null) || orderBy.trim().equals("")) {
			return createCriteria(entityClass, criterions);
		} else {
			Criteria criteria = createCriteria(entityClass, criterions);

			if (isAsc) {
				criteria.addOrder(Order.asc(orderBy));
			} else {
				criteria.addOrder(Order.desc(orderBy));
			}

			return criteria;
		}
	}

	/**
	 * 根据entityClass生成对应类型的Criteria.
	 *
	 * @param entityClass 实体类型
	 * @param criterions 条件
	 * @return Criteria
	 */
	public Criteria createCriteria(Class entityClass, Criterion... criterions) {
		Criteria criteria = getSession().createCriteria(entityClass);

		for (Criterion c : criterions) {
			criteria.add(c);
		}

		return criteria;
	}

	public T get(ID id) {
		log.info("" + this.entityClass);
		return get(this.entityClass, id);
	}

	public T get(Class<T> entityClass, ID id) {
		return (T) super.getHibernateTemplate().get(entityClass, id);
	}

	public T load(ID id) {
		return (T) super.getHibernateTemplate().load(entityClass, id);
	}

	public List<T> getAll(boolean cacheQueries) {
		return setCacheQueries(cacheQueries).loadAll(entityClass);
	}

	public List<T> getAll() {
		return getHibernateTemplate().loadAll(entityClass);
	}
	public T findUniqueByNamedQuery(String queryName, Object... values){
		return (T)getNamedQuery(queryName, values).uniqueResult();
	}
	protected HibernateTemplate setCacheQueries(boolean cacheQueries) {
		HibernateTemplate template = super.getHibernateTemplate();
		template.setCacheQueries(cacheQueries);
		return template;
	}

	public List<T> findByHQL(String hql) {
		return (List<T>) super.getHibernateTemplate().find(hql);
	}

	public List<T> findByHql(String hql, Object... values) {
		return super.getHibernateTemplate().find(hql, values);
	}

	public Object findUnique(String hql, Object... values) {

		return createQuery(hql, values).uniqueResult();
	}

	public T findUniqueByHql(String queryString, Object... values) {
		return (T) createQuery(queryString, values).uniqueResult();
	}

	public Object findUniqueBySql(String sql, Object... values) {

		return createSQLQuery(sql, values).uniqueResult();
	}

	public Object findUniqueBySql(String sql, Map<String, Object> values) {

		return createSQLQuery(sql, values).uniqueResult();
	}

	public void update(T entity) {
		super.getHibernateTemplate().update(entity);
	}

	public void updateAll(List<T> entities) {
		super.getHibernateTemplate().saveOrUpdateAll(entities);
	}

	public List<T> findByCriteria(Collection<Criterion> criterion) {
		DetachedCriteria detachedCrit = DetachedCriteria.forClass(entityClass);
		for (Criterion c : criterion) {
			detachedCrit.add(c);
		}
		return getHibernateTemplate().findByCriteria(detachedCrit);
	}

	public void deleteAll(Collection<T> entities) {
		super.getHibernateTemplate().deleteAll(entities);
	}

	// 加锁并删除指定的实体
	public void deleteWithLock(T entity, LockMode lock) {
		getHibernateTemplate().delete(entity, lock);
		this.flush(); // 立即刷新，否则锁不会生效。
	}

	public void lock(T entity, LockMode lockMode) {
		super.getHibernateTemplate().lock(entity, lockMode);

	}

	// 使用HSQL语句直接增加、更新、删除实体
	public int bulkUpdate(String queryString) {
		return getHibernateTemplate().bulkUpdate(queryString);
	}

	// 使用带参数的HSQL语句增加、更新、删除实体
	public int bulkUpdate(String queryString, Object... values) {
		return getHibernateTemplate().bulkUpdate(queryString, values);
	}

	public Object getStatValue(DetachedCriteria criteria, String propertyName, String StatName) {
		if (StatName.toLowerCase().equals("max"))
			criteria.setProjection(Projections.max(propertyName));
		else if (StatName.toLowerCase().equals("min"))
			criteria.setProjection(Projections.min(propertyName));
		else if (StatName.toLowerCase().equals("avg"))
			criteria.setProjection(Projections.avg(propertyName));
		else if (StatName.toLowerCase().equals("sum"))
			criteria.setProjection(Projections.sum(propertyName));
		else
			return null;
		List list = this.findByCriteria(criteria, 0, 1);
		return list.get(0);
	}

	public List<T> findByCriteria(DetachedCriteria criteria, int firstResult, int maxResults) {
		return getHibernateTemplate().findByCriteria(criteria, firstResult, maxResults);
	}

	public List<T> findByCriteria(Criterion[] criterions) {
		// TODO Auto-generated method stub
		return null;
	}

	public Integer getRowCount(DetachedCriteria criteria) {

		return (Integer) super.getHibernateTemplate().findByCriteria(criteria).get(0);
	}

	public Integer count() {//上面的用法
		DetachedCriteria criteria = createDetachedCriteria();
		criteria.setProjection(Projections.rowCount());
		return getRowCount(criteria);
	}

	public void clear() {
		getSession().clear();
	}

	public boolean contains(T t) throws DataAccessException {
		return getHibernateTemplate().contains(t);
	}

	public Iterator<T> iterate(String hql, Object... values) {
		return getHibernateTemplate().iterate(hql, values);
	}

	public List<T> findByNamedQuery(String queryName, String[] paramNames, Object[] values) {
		return super.getHibernateTemplate().findByNamedQueryAndNamedParam(queryName, paramNames, values);
	}

	public List<T> findByNamedQuery(String queryName, Object... values) {
		return super.getHibernateTemplate().findByNamedQuery(queryName, values);
	}

	public List<T> findByNamedQuery(String queryName) {
		return super.getHibernateTemplate().findByNamedQuery(queryName);
	}

	// 创建与会话无关的检索标准
	public DetachedCriteria createDetachedCriteria() {
		return DetachedCriteria.forClass(this.entityClass);
	}

	// 创建与会话绑定的检索标准
	public Criteria createCriteria() {
		return this.createDetachedCriteria().getExecutableCriteria(this.getSession());
	}

	public void flush() {
		getHibernateTemplate().flush();
	}

	public Query createQuery(String queryString, Object... values) {
		int i;
		Assert.hasText(queryString);
		Query query = getCurrentSession().createQuery(queryString);
		if (values != null)
			for (i = 0; i < values.length; ++i)
				query.setParameter(i, values[i]);

		return query;
	}
	protected Query getNamedQuery(String queryName, Object... values){
		int i;
		Assert.hasText(queryName);
		Query query = getCurrentSession().getNamedQuery(queryName);
		if (values != null)
			for (i = 0; i < values.length; ++i)
				query.setParameter(i, values[i]);

		return query;
	}
	protected Query createSQLQuery(String queryString, Object... values) {
		int i;
		Assert.hasText(queryString);
		Query query = getCurrentSession().createSQLQuery(queryString);
		if (values != null)
			for (i = 0; i < values.length; ++i)
				query.setParameter(i, values[i]);

		return query;
	}

	protected Query createSQLQuery(String queryString, Map<String, Object> values) {
		Assert.hasText(queryString);
		Query query = getCurrentSession().createSQLQuery(queryString);
		if (values != null)
			for (Map.Entry<String, Object> entry : values.entrySet())
				query.setParameter(entry.getKey(), entry.getValue());

		return query;
	}

	public List<T> findByProperty(String propertyName, Object value, boolean cacheable) {
		Assert.hasText(propertyName);
		Criterion criterion = Restrictions.eq(propertyName, value);
		Criteria criteria = createCriteria();
		criteria.add(criterion);
		criteria.setCacheable(cacheable);
		return criteria.list();

	}

	public List<T> findByProperty(String propertyName, Object value) {
		return findByProperty(propertyName, value, false);
	}

	public List<T> findByProperty(Map<String, Object> values) {
		Criterion criterion = Restrictions.allEq(values);
		Criteria criteria = createCriteria();
		criteria.add(criterion);
		return criteria.list();
	}

	public T findUniqueByProperty(String propertyName, Object value) {
		Assert.hasText(propertyName);
		Criterion criterion = Restrictions.eq(propertyName, value);
		return (T) createCriteria(new Criterion[] { criterion }).uniqueResult();
	}

	public List<T> findByExample(T entity) {
		return getHibernateTemplate().findByExample(entity);
	}

	protected Criteria createCriteria(Criterion...criterions) {
		Criteria criteria = getCurrentSession().createCriteria(this.entityClass);
		Criterion[] arr$ = criterions;
		int len$ = arr$.length;
		for (int i$ = 0; i$ < len$; ++i$) {
			Criterion c = arr$[i$];
			criteria.add(c);
		}
		if (isCacheable())
			criteria.setCacheable(true);
		return criteria;
	}

	public T findByUnique(String propertyName, Object value) {
		Assert.hasText(propertyName, "propertyName不能为空");
		Criterion criterion = Restrictions.eq(propertyName, value);
		return (T) createCriteria(new Criterion[] { criterion }).uniqueResult();
	}

	public T findByUnique(String propertyName, boolean cacheable, Object value) {
		Assert.hasText(propertyName, "propertyName不能为空");
		Criterion criterion = Restrictions.eq(propertyName, value);
		return (T) createCriteria(new Criterion[] { criterion }).setCacheable(cacheable).uniqueResult();
	}

	public List<T> find(String queryString, Object... values) {
		return findByHql(queryString, values);

	}

	public boolean isPropertyUnique(String propertyName, Object newValue, Object orgValue) {
		if ((newValue == null) || (newValue.equals(orgValue)))
			return true;
		Object object = findByUnique(propertyName, newValue);
		return (object == null);
	}

	protected Criterion[] buildFilterCriterions(List<PropertyFilter> filters) {
		List criterionList = new ArrayList();
		for (PropertyFilter filter : filters) {
			String propertyName = filter.getPropertyName();

			boolean multiProperty = StringUtils.contains(propertyName, "__");
			if (!(multiProperty)) {
				Criterion criterion = buildPropertyCriterion(propertyName, filter.getValue(), filter.getMatchType());
				criterionList.add(criterion);
			} else {
				Disjunction disjunction = Restrictions.disjunction();
				String[] params = StringUtils.split(propertyName, "__");

				String[] arr$ = params;
				int len$ = arr$.length;
				for (int i$ = 0; i$ < len$; ++i$) {
					String param = arr$[i$];
					Criterion criterion = buildPropertyCriterion(param, filter.getValue(), filter.getMatchType());
					disjunction.add(criterion);
				}
				criterionList.add(disjunction);
			}
		}
		return ((Criterion[]) criterionList.toArray(new Criterion[criterionList.size()]));
	}

	protected Criterion buildPropertyCriterion(String propertyName, Object value, PropertyFilter.MatchType matchType) {
		Assert.hasText(propertyName, "propertyName不能为空");
		Criterion criterion = null;

		if (PropertyFilter.MatchType.EQ.equals(matchType))
			criterion = Restrictions.eq(propertyName, value);

		if (PropertyFilter.MatchType.LIKE.equals(matchType)) {
			criterion = Restrictions.like(propertyName, (String) value, MatchMode.ANYWHERE);
		}

		return criterion;
	}

	protected Session getCurrentSession() {
		return super.getHibernateTemplate().getSessionFactory().getCurrentSession();
	}

	protected int countCriteriaResult(Criteria c) {
		CriteriaImpl impl = (CriteriaImpl) c;

		Projection projection = impl.getProjection();
		ResultTransformer transformer = impl.getResultTransformer();

		List orderEntries = null;
		try {
			orderEntries = (List) ReflectionUtils.getFieldValue(impl, "orderEntries");
			ReflectionUtils.setFieldValue(impl, "orderEntries", new ArrayList());
		} catch (Exception e) {
			this.log.error("不可能抛出的异常:{}", e.getMessage());
		}

		int totalCount = ((Integer) c.setProjection(Projections.rowCount()).uniqueResult()).intValue();

		c.setProjection(projection);

		if (projection == null)
			c.setResultTransformer(CriteriaSpecification.ROOT_ENTITY);

		if (transformer != null)
			c.setResultTransformer(transformer);
		try {
			ReflectionUtils.setFieldValue(impl, "orderEntries", orderEntries);
		} catch (Exception e) {
			this.log.error("不可能抛出的异常:{}", e.getMessage());
		}

		return totalCount;
	}

	public Map<String, Object> findBySqlUniqueToMap(String queryString, Map<String, Object> values) {
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		return (Map<String, Object>) query.uniqueResult();
	}

	public List<Map<String, Object>> findBySqlToMapList(String queryString, Map<String, Object> values) {
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		return query.list();
	}

	public List<Map<String, Object>> findBySqlToMapList(String queryString, Object... values) {
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		return query.list();
	}

	public List<Object> findBySqlToList(String queryString, Map<String, Object> values) {
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.TO_LIST);
		return query.list();
	}

	public List<Object> findBySqlToList(String queryString, Object... values) {
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.TO_LIST);
		return query.list();
	}

	public List<Map<String, Object>> findBySqlToMapList(String queryString, Map<String, Object> values,
			int firstResult, int maxResults) {
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		query.setFirstResult(firstResult).setMaxResults(maxResults);
		return query.list();
	}

	public Map<String, Object> findBySqlUniqueToMap(String queryString, Object... values) {
		Query query = createSQLQuery(queryString, values);
		query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
		return (Map<String, Object>) query.uniqueResult();
	}

	public int executeSql(String queryString, Map<String, Object> values) {
		Query query = createSQLQuery(queryString, values);
		return query.executeUpdate();
	}

	public int executeSql(String queryString, Object... values) {
		Query query = createSQLQuery(queryString, values);
		return query.executeUpdate();
	}

	public boolean isCacheable() {
		return cacheable;
	}

	public void setCacheable(boolean cacheable) {
		this.cacheable = cacheable;
	}

	public void saveOrUpdateAll(Collection<T> entities) {
		super.getHibernateTemplate().saveOrUpdateAll(entities);
		/*	Session session = getCurrentSession();
			for (Iterator it = entities.iterator(); it.hasNext(); session.saveOrUpdate(it.next()))
				;*/
	}

	protected Connection getConnectionByDataSource() throws SQLException {
		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/applicationContext*.xml");
		DataSource dataSource = (DataSource) ctx.getBean("dataSource");
		Connection connection = dataSource.getConnection();
		connection.setAutoCommit(false);
		return connection;
	}

	@SuppressWarnings("deprecation")
	protected Connection getConnection() throws SQLException {
		return getCurrentSession().connection();
	}

	public void deleteObject(Object entity) {
		Assert.notNull(entity);
		getHibernateTemplate().delete(entity);

	}

	public void saveObject(Object entity) {
		Assert.notNull(entity);
		getHibernateTemplate().save(entity);

	}

	public void updateObject(Object entity) {
		Assert.notNull(entity);
		getHibernateTemplate().update(entity);

	}

	protected PreparedStatement setParams(PreparedStatement ps, Object... values) throws SQLException {
		for (int i = 0; i < values.length; i++) {
			//System.out.println(values[i]);
			ps.setObject(i + 1, values[i]);
		}
		return ps;
	}

	/**
	 * 创建Criteria对象，带排序字段与升降序字段.
	 *
	 * @see #createCriteria(Class,Criterion[])
	 */
	protected Criteria createCriteria(String orderBy, boolean isAsc, Criterion... criterions) {
		Assert.hasText(orderBy);

		Criteria criteria = createCriteria(criterions);

		if (isAsc)
			criteria.addOrder(Order.asc(orderBy));
		else
			criteria.addOrder(Order.desc(orderBy));

		return criteria;
	}

	protected Class<T> typeClass() {
		return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}
	  /**
     * 根据主键删除记录
     * @param id
     */
    public void removeById(ID id){
        Map map = getSessionFactory().getAllClassMetadata();
        SingleTableEntityPersister p = (SingleTableEntityPersister)map.get(entityClass.getName());
        String idName = p.getIdentifierPropertyName();
        String hql = "delete from "+entityClass.getName()+" where "+idName+"=?";
        getHibernateTemplate().bulkUpdate(hql, id);
    }
    /**
	 * 获取全部对象,带排序字段与升降序参数.
	 */
	public  List<T> getAll(Class entityClass, String orderBy, boolean isAsc) {
		Assert.hasText(orderBy);
		if (isAsc)
			return getHibernateTemplate().findByCriteria(
					DetachedCriteria.forClass(entityClass).addOrder(Order.asc(orderBy)));
		else
			return getHibernateTemplate().findByCriteria(
					DetachedCriteria.forClass(entityClass).addOrder(Order.desc(orderBy)));
	}
	/**
	 * 判断对象某列的值在数据库中不存在重复
	 * 
	 * @param names
	 *            在POJO里相对应的属性名,列组合时以逗号分割<br>
	 *            如"name,loginid,password"
	 */
	public boolean isNotUnique(T entity, String names) {
		Assert.hasText(names);
		Criteria criteria = createCriteria(entityClass).setProjection(Projections.rowCount());
		String[] nameList = names.split(",");
		try {
			for (String name : nameList) {
				criteria.add(Restrictions.eq(name, PropertyUtils.getProperty(entity, name)));
			}

			String idName = getIdName(entityClass);
			if (idName != null) {
				Object id = PropertyUtils.getProperty(entity, idName);
				// 如果是update,排除自身
				if (id != null)
					criteria.add(Restrictions.not(Restrictions.eq(idName, id)));
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
			return false;
		}
		return Convert.castToNumber(criteria.uniqueResult()).intValue() > 0;
	}

    /**
     * 批量更新业务对象
     * add by chenmk 2008.01.22
     *
     * @param objList
     */
    public void updateBatch(List<T> objList){

        if(objList == null || objList.size() == 0)
            return;

        int i = 0;

        for(T obj : objList){

            update(obj);

            /*
             * 将本批插入的对象立即写入数据库并释放内存
             * 如果要将很多对象持久化，你必须通过经常的调用 flush() 以及稍后调用 clear() 来控制第一级缓存的大小             *
             */
            if(++i % 20 == 0){
                flush();
                clear();
            }
        }
    }
    /**
     * 批量保存
     * add by chenmk 2008.01.22
     *
     * @param objList
     */
    public void saveBatch(List<T> objList) {
        if (objList == null || objList.size() == 0)
            return;

        int i = 0;

        for(T obj : objList){

            save(obj);

            /*
             * 将本批插入的对象立即写入数据库并释放内存
             * 如果要将很多对象持久化，你必须通过经常的调用 flush() 以及稍后调用 clear() 来控制第一级缓存的大小             *
             */
            if(++i % 20 == 0){
                flush();
                clear();
            }
        }
    }

	public void saveAll(Collection<T> entities) {
		for (Iterator it = entities.iterator(); it.hasNext(); getCurrentSession().save(it.next()))
			;
	}

	public List<T> findByLike(String propertyName, String value) {
		return findByLike(entityClass, propertyName, value);

	}
}
